﻿#ifndef JZLOG_MANAGER_H_
#define JZLOG_MANAGER_H_

#include <QObject>
#include <QString>
#include <QMutex>
#include <QFile>
#include <QTimer>
#include <QDate>
#include <QMap>
#include <QSharedPointer>
#include <QPointer>
#include <QEvent>

enum {
    LOG_DEBUG,
    LOG_INFO,
    LOG_WARNING,
    LOG_ERROR,
    LOG_FATAL,
};

enum {
    LogModule_General,
    LogModule_User = 100,
};

class JZLogModuleConfig
{
public:
    enum{
        None,
        File = 0x1,
        Console = 0x2,
    };

    JZLogModuleConfig();

    QString name;
    int type;
};

class JZLogObject
{
public:
    static QSharedPointer<JZLogObject> makeLog(int module, int level, QString message);

    int module;
    int level;
    int64_t time;        
    QString message;    
};
typedef QSharedPointer<JZLogObject> JZLogObjectPtr;

class JZLogEvent : public QEvent
{
public:
    static int EventType;
    
    JZLogEvent();
    JZLogObjectPtr log;
};

class JZLogManager : public QObject
{
    Q_OBJECT

public:
    static JZLogManager *instance();

    void init();

    void addObserver(int module,QObject *recv);
    void removeObserver(int module, QObject *recv);

    QString logPath();
    void setLogPath(QString path);

    void addModule(int module,JZLogModuleConfig config);
    QString moduleName(int module);

    JZLogModuleConfig moduleConfig(int id);
    void setModuleConfig(int id,JZLogModuleConfig config);

    void log(int module, int level, const QString &format);
    void logFmt(int module, int level, const char *format, ...);

protected slots:
    void onTimeOut();

protected:
    class JZLogModule
    {
    public:
        JZLogModuleConfig config;
        QList<QPointer<QObject>> recvObjects;
        QList<JZLogObjectPtr> logCache;
        QFile file;
    };

    JZLogManager();
    ~JZLogManager();
    
    void flushFile();
    void createFile(JZLogModule *module);

    QMap<int,JZLogModule*> m_modules;
    QTimer *m_timer;
    QString m_logPath;
    QMutex m_lock;
    QDateTime m_flushTime;
};

#define LOG_D(format) JZLogManager::instance()->log(LogModule_General,LOG_DEBUG,format)
#define LOG_I(format) JZLogManager::instance()->log(LogModule_General,LOG_INFO,format)
#define LOG_W(format) JZLogManager::instance()->log(LogModule_General,LOG_WARNING,format)
#define LOG_E(format) JZLogManager::instance()->log(LogModule_General,LOG_ERROR,format)
#define LOG_F(format) JZLogManager::instance()->log(LogModule_General,LOG_FATAL,format)

#define LOGMOD_D(module,format) JZLogManager::instance()->log(module,LOG_DEBUG,format)
#define LOGMOD_I(module,format) JZLogManager::instance()->log(module,LOG_INFO,format)
#define LOGMOD_W(module,format) JZLogManager::instance()->log(module,LOG_WARNING,format)
#define LOGMOD_E(module,format) JZLogManager::instance()->log(module,LOG_ERROR,format)
#define LOGMOD_F(module,format) JZLogManager::instance()->log(module,LOG_FATAL,format)

#define LOG_FMT_D(format,...) JZLogManager::instance()->logFmt(LogModule_General,LOG_DEBUG,format,##__VA_ARGS__)
#define LOG_FMT_I(format,...) JZLogManager::instance()->logFmt(LogModule_General,LOG_INFO,format,##__VA_ARGS__)
#define LOG_FMT_W(format,...) JZLogManager::instance()->logFmt(LogModule_General,LOG_WARNING,format,##__VA_ARGS__)
#define LOG_FMT_E(format,...) JZLogManager::instance()->logFmt(LogModule_General,LOG_ERROR,format,##__VA_ARGS__)
#define LOG_FMT_F(format,...) JZLogManager::instance()->logFmt(LogModule_General,LOG_FATAL,format,##__VA_ARGS__)

#define LOGMOD_FMT_D(module,format,...) JZLogManager::instance()->logFmt(module,LOG_DEBUG,format,##__VA_ARGS__)
#define LOGMOD_FMT_I(module,format,...) JZLogManager::instance()->logFmt(module,LOG_INFO,format,##__VA_ARGS__)
#define LOGMOD_FMT_W(module,format,...) JZLogManager::instance()->logFmt(module,LOG_WARNING,format,##__VA_ARGS__)
#define LOGMOD_FMT_E(module,format,...) JZLogManager::instance()->logFmt(module,LOG_ERROR,format,##__VA_ARGS__)
#define LOGMOD_FMT_F(module,format,...) JZLogManager::instance()->logFmt(module,LOG_FATAL,format,##__VA_ARGS__)


#endif